import axios, {
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type CancelTokenSource,
  type InternalAxiosRequestConfig,
} from 'axios'

import { message, notification } from 'ant-design-vue'
import { useRouter } from 'vue-router'
const router = useRouter()

// 定义API响应的基础结构
interface ApiResponse<T = any> {
  code: number
  message: string
  data: T
  success: boolean
}

// 错误码枚举
enum ErrorCode {
  SUCCESS = 200, // 成功
  UNAUTHORIZED = 401, // 未授权/登录过期
  FORBIDDEN = 403, // 禁止访问
  NOT_FOUND = 404, // 资源不存在
  SERVER_ERROR = 500, // 服务器错误
}

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_PREFIX, // 从环境变量获取基础URL
  timeout: 10000, // 超时时间
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
})

// 存储请求取消令牌，用于取消请求
const cancelTokenSources = new Map<string, CancelTokenSource>()

/**
 * 生成请求唯一标识
 * @param config 请求配置
 */
const generateRequestKey = (config: AxiosRequestConfig): string => {
  const { method, url, params, data } = config
  return [
    method?.toUpperCase(),
    url,
    params ? JSON.stringify(params) : '',
    data ? JSON.stringify(data) : '',
  ].join('&')
}

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 生成请求唯一标识
    const requestKey = generateRequestKey(config)

    // 如果存在相同请求，取消之前的请求
    if (cancelTokenSources.has(requestKey)) {
      const source = cancelTokenSources.get(requestKey)
      source?.cancel('重复请求已被取消')
      cancelTokenSources.delete(requestKey)
    }

    // 创建新的取消令牌
    const source = axios.CancelToken.source()
    config.cancelToken = source.token
    cancelTokenSources.set(requestKey, source)

    // 添加token
    // const token = getToken()
    // if (token && config.headers) {
    //   config.headers.Authorization = `Bearer ${token}`
    // }

    return config
  },
  (error) => {
    // 处理请求错误
    message.error('请求参数错误')
    return Promise.reject(error)
  },
)

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>) => {
    // 移除已完成请求的取消令牌
    const requestKey = generateRequestKey(response.config)
    cancelTokenSources.delete(requestKey)

    const { data } = response
    console.log(response)

    // 处理业务逻辑错误
    if (!data.success || data.code !== ErrorCode.SUCCESS) {
      // 显示错误信息
      message.error(data.message || '操作失败')
      return Promise.reject(new Error(data.message || '接口请求失败'))
    }

    return data.data
  },
  (error) => {
    // 移除已完成请求的取消令牌
    if (error.config) {
      const requestKey = generateRequestKey(error.config)
      cancelTokenSources.delete(requestKey)
    }

    // 处理取消请求的错误
    if (axios.isCancel(error)) {
      console.log('请求已取消:', error.message)
      return Promise.reject(error)
    }

    // 处理HTTP错误
    const response = error.response

    if (response) {
      switch (response.status) {
        case ErrorCode.UNAUTHORIZED:
          // 未授权，清除token并跳转登录页
          message.error('登录已过期，请重新登录')
          router.push('/login')
          break
        case ErrorCode.FORBIDDEN:
          notification.error({
            message: '访问被拒绝',
            description: '您没有足够的权限执行此操作',
          })
          break
        case ErrorCode.NOT_FOUND:
          message.error('请求的资源不存在')
          break
        case ErrorCode.SERVER_ERROR:
          notification.error({
            message: '服务器错误',
            description: '服务器内部错误，请稍后再试',
          })
          break
        default:
          message.error(`请求错误: ${response.status}`)
      }
    } else if (error.message.includes('timeout')) {
      // 处理超时错误
      message.error('请求超时，请稍后再试')
    } else {
      // 处理网络错误
      message.error('网络连接错误，请检查网络')
    }

    return Promise.reject(error)
  },
)

/**
 * 封装请求方法
 * @param config axios配置
 */
const request = <T = any>(config: AxiosRequestConfig): Promise<T> => {
  return service(config) as Promise<T>
}

/**
 * GET请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 额外配置
 */
const get = <T = any>(
  url: string,
  params?: Record<string, any>,
  config?: AxiosRequestConfig,
): Promise<T> => {
  return request<T>({
    method: 'get',
    url,
    params,
    ...config,
  })
}

/**
 * POST请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 额外配置
 */
const post = <T = any>(
  url: string,
  data?: Record<string, any>,
  config?: AxiosRequestConfig,
): Promise<T> => {
  return request<T>({
    method: 'post',
    url,
    data,
    ...config,
  })
}

/**
 * PUT请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 额外配置
 */
const put = <T = any>(
  url: string,
  data?: Record<string, any>,
  config?: AxiosRequestConfig,
): Promise<T> => {
  return request<T>({
    method: 'put',
    url,
    data,
    ...config,
  })
}

/**
 * DELETE请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 额外配置
 */
const del = <T = any>(
  url: string,
  params?: Record<string, any>,
  config?: AxiosRequestConfig,
): Promise<T> => {
  return request<T>({
    method: 'delete',
    url,
    params,
    ...config,
  })
}

/**
 * 取消所有请求
 */
const cancelAllRequests = (): void => {
  cancelTokenSources.forEach((source) => {
    source.cancel('所有请求已被取消')
  })
  cancelTokenSources.clear()
}

export default {
  request,
  get,
  post,
  put,
  delete: del, // 使用delete作为属性名需要用别名
  cancelAllRequests,
}
